Skip to content

Conversation

@bernhardmgruber
Copy link
Contributor

@bernhardmgruber bernhardmgruber commented Dec 8, 2025

Fixes: #6919
Fixes: #5057
Fixes: #3017

Compile time of cub.test.device.transform.lid_0 using nvcc 13.0 and clang 20 for sm86, sm120

branch:
1m49.900s
1m50.615s
1m50.255s

main:
1m56.917s
1m57.378s
1m59.371s

Compile time of cub.test.device.transform.lid_0 for sm86, sm120 using clang 20 in CUDA mode:

branch:
real 1m40.627s
real 1m40.675s
real 1m40.912s

main:
real 1m39.273s
real 1m39.669s
real 1m39.835s

@copy-pr-bot
Copy link
Contributor

copy-pr-bot bot commented Dec 8, 2025

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@cccl-authenticator-app cccl-authenticator-app bot moved this from Todo to In Progress in CCCL Dec 8, 2025
@bernhardmgruber bernhardmgruber marked this pull request as ready for review December 9, 2025 07:44
@bernhardmgruber bernhardmgruber requested review from a team as code owners December 9, 2025 07:44
@cccl-authenticator-app cccl-authenticator-app bot moved this from In Progress to In Review in CCCL Dec 9, 2025
@github-actions

This comment has been minimized.

Comment on lines 986 to 1014
#if _CCCL_HAS_CONCEPTS()
requires transform_policy_hub<ArchPolicies>
#endif // _CCCL_HAS_CONCEPTS()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: I believe we should either use the concept emulation or plain SFINAE in C++17 too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. We could also static_assert, but ArchPolicies is already used in the kernel attributes before we reach the body. And using a static_assert would only be evaluated in the device path.

How would I write that using concept emulation and have the concept check before the __launch_bounds__?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could write:

Suggested change
#if _CCCL_HAS_CONCEPTS()
requires transform_policy_hub<ArchPolicies>
#endif // _CCCL_HAS_CONCEPTS()
_CCCL_TEMPLATE(typename PolicySelector,
typename Offset,
typename Predicate,
typename F,
typename RandomAccessIteratorOut,
typename... RandomAccessIteratorsIn)
_CCCL_REQUIRES(transform_policy_selector<PolicySelector>)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but as discussed on Slack before, we would need to get transform_policy_selector and then policy_selector working, which we couldn't of the is_constant_expression check. Let's leave it.

Comment on lines +358 to +380
bool all_inputs_contiguous = true;
bool all_input_values_trivially_reloc = true;
bool can_memcpy_contiguous_inputs = true;
bool all_value_types_have_power_of_two_size = ::cuda::is_power_of_two(output.value_type_size);
for (const auto& input : inputs)
{
all_inputs_contiguous &= input.is_contiguous;
all_input_values_trivially_reloc &= input.value_type_is_trivially_relocatable;
// the vectorized kernel supports mixing contiguous and non-contiguous iterators
can_memcpy_contiguous_inputs &= !input.is_contiguous || input.value_type_is_trivially_relocatable;
all_value_types_have_power_of_two_size &= ::cuda::is_power_of_two(input.value_type_size);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: While it is technically more efficient, I believe it would improve readability if we did

    const bool all_inputs_contiguous = ::cuda::std::all_of(input.begin(), input.end(), [](const auto& input) { return input.is_contiguous; })

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I do this later? Maybe we have std::ranges::all_of by then.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@bernhardmgruber
Copy link
Contributor Author

bernhardmgruber commented Dec 11, 2025

I see tiny changes in the generated SASS for cub.bench.transform.babelstream.base, notable in the filling kernels (no inputs) for complex<float>. The compiler now generates STG.E.ENL2.256, which it didn't do before.

The fill lernel for int128 seems to have degraded from generating STG.E.128 to a lot more STG.E.

All kernels with a functor marked as __callable_permitting_copied_arguments show no changes. That's good.

It feels a bit like the items per thread changed for the fill kernels.

@bernhardmgruber
Copy link
Contributor Author

It feels a bit like the items per thread changed for the fill kernels.

They did. Before we had a tuning policy for sm_120, that was not taken into account :D This PR now uses it.

@bernhardmgruber
Copy link
Contributor Author

I disabled the sm120 fill policy and now the only SASS diff for filling is on:

void cub::_V_300300_SM_1200::detail::transform::transform_kernel<cub::_V_300300_SM_1200::detail::transform::policy_hub<false, true, cuda::std::__4::tuple<cuda::__4::counting_iterator<long, 0, 0>>, unsigned long*>::policy1000, long, cub::_V_300300_SM_1200::detail::transform::always_true_predicate, cuda::__4::__callable_permitting_copied_arguments<(anonymous namespace)::lognormal_adjust_t<unsigned long>>, unsigned long*, cuda::__4::counting_iterator<long, 0, 0>>(long, int, bool, cub::_V_300300_SM_1200::detail::transform::always_true_predicate, cuda::__4::__callable_permitting_copied_arguments<(anonymous namespace)::lognormal_adjust_t<unsigned long>>, unsigned long*, cub::_V_300300_SM_1200::detail::transform::kernel_arg<cuda::__4::counting_iterator<long, 0, 0>>)

which is a thrust::tabulate of a counting_iterator<long> and an unsigned long*.

@gonidelis gonidelis self-requested a review December 11, 2025 16:44
@bernhardmgruber
Copy link
Contributor Author

Found the final issue with the fill kernels. Disabled the vectorized tunings when we have input streams (they were tuned for output only use cases). SASS of cub.bench.transform.fill.base now matches baseline on sm120.

Copy link
Collaborator

@gevtushenko gevtushenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excited to see the new tuning machinery at work! Code is much more readable now and we no longer have to parse PTX 🎉

@github-actions

This comment has been minimized.

@bernhardmgruber
Copy link
Contributor Author

bernhardmgruber commented Jan 15, 2026

I see EVO correctly failing to build invalid parameter configurations:

2026-01-15 12:55:46,259: starting build for cub.bench.transform.babelstream.bif_-8.alg_3.tpb_384.vsp2_2.vpt_2: cmake --build . --target cub.bench.transform.babelstream.variant
2026-01-15 12:55:52,387: finished build for cub.bench.transform.babelstream.bif_-8.alg_3.tpb_384.vsp2_2.vpt_2 (exit code: 2) in 6.128s
2026-01-15 12:55:53,348: found cached base build for cub.bench.transform.babelstream.base
2026-01-15 12:55:53,352: found cached base build for cub.bench.transform.babelstream.base
2026-01-15 12:55:58,146: starting build for cub.bench.transform.babelstream.bif_-16.alg_0.tpb_512.vsp2_4.vpt_3: cmake --build . --target cub.bench.transform.babelstream.variant
2026-01-15 12:56:05,124: finished build for cub.bench.transform.babelstream.bif_-16.alg_0.tpb_512.vsp2_4.vpt_3 (exit code: 2) in 6.978s
2026-01-15 12:56:06,090: found cached base build for cub.bench.transform.babelstream.base
2026-01-15 12:56:06,094: found cached base build for cub.bench.transform.babelstream.base
2026-01-15 12:56:07,406: starting build for cub.bench.transform.babelstream.bif_0.alg_2.tpb_128.vsp2_2.vpt_1: cmake --build . --target cub.bench.transform.babelstream.variant
2026-01-15 12:56:14,887: finished build for cub.bench.transform.babelstream.bif_0.alg_2.tpb_128.vsp2_2.vpt_1 (exit code: 2) in 7.481s
2026-01-15 12:56:47,128: found cached base build for cub.bench.transform.babelstream.base
2026-01-15 12:56:47,134: found cached base build for cub.bench.transform.babelstream.base
2026-01-15 12:56:55,717: starting build for cub.bench.transform.babelstream.bif_-4.alg_1.tpb_512.vsp2_5.vpt_1: cmake --build . --target cub.bench.transform.babelstream.variant
2026-01-15 12:57:23,938: finished build for cub.bench.transform.babelstream.bif_-4.alg_1.tpb_512.vsp2_5.vpt_1 (exit code: 0) in 28.221s

What's a bit worrying is that in the course of 4h and across 8 GPUs not a single algorithm other than 1 succeeded in building. This may suggest we need a different approach, but we can address this later.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

🥳 CI Workflow Results

🟩 Finished in 7h 49m: Pass: 100%/133 | Total: 1d 20h | Max: 4h 29m | Hits: 98%/177904

See results here.

@bernhardmgruber bernhardmgruber merged commit 6e592be into NVIDIA:main Jan 15, 2026
282 of 285 checks passed
@github-project-automation github-project-automation bot moved this from In Review to Done in CCCL Jan 15, 2026
@bernhardmgruber bernhardmgruber deleted the tuning_transform branch January 15, 2026 22:46
bernhardmgruber added a commit to bernhardmgruber/cccl that referenced this pull request Jan 15, 2026
PR NVIDIA#6914 seems to have missed a few pieces to remove
bernhardmgruber added a commit that referenced this pull request Jan 16, 2026
PR #6914 seems to have missed a few pieces to remove
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Implement the new tuning API for DeviceTransform Make cub::DeviceTransform tunable Expose cub::DeviceTransform BIF to tuning

3 participants